home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Zoners Half-Life Tools / common / bspfile.cpp < prev    next >
C/C++ Source or Header  |  2002-11-14  |  29KB  |  884 lines

  1. #include "cmdlib.h"
  2. #include "filelib.h"
  3. #include "messages.h"
  4. #include "hlassert.h"
  5. #include "log.h"
  6. #include "mathlib.h"
  7. #include "bspfile.h"
  8. #include "scriplib.h"
  9. #include "blockmem.h"
  10.  
  11. //=============================================================================
  12.  
  13. int             g_max_map_miptex = DEFAULT_MAX_MAP_MIPTEX;
  14.  
  15. int             g_nummodels;
  16. dmodel_t        g_dmodels[MAX_MAP_MODELS];
  17. int             g_dmodels_checksum;
  18.  
  19. int             g_visdatasize;
  20. byte            g_dvisdata[MAX_MAP_VISIBILITY];
  21. int             g_dvisdata_checksum;
  22.  
  23. int             g_lightdatasize;
  24. byte            g_dlightdata[MAX_MAP_LIGHTING];
  25. int             g_dlightdata_checksum;
  26.  
  27. int             g_texdatasize;
  28. byte*           g_dtexdata;                                  // (dmiptexlump_t)
  29. int             g_dtexdata_checksum;
  30.  
  31. int             g_entdatasize;
  32. char            g_dentdata[MAX_MAP_ENTSTRING];
  33. int             g_dentdata_checksum;
  34.  
  35. int             g_numleafs;
  36. dleaf_t         g_dleafs[MAX_MAP_LEAFS];
  37. int             g_dleafs_checksum;
  38.  
  39. int             g_numplanes;
  40. dplane_t        g_dplanes[MAX_MAP_PLANES];
  41. int             g_dplanes_checksum;
  42.  
  43. int             g_numvertexes;
  44. dvertex_t       g_dvertexes[MAX_MAP_VERTS];
  45. int             g_dvertexes_checksum;
  46.  
  47. int             g_numnodes;
  48. dnode_t         g_dnodes[MAX_MAP_NODES];
  49. int             g_dnodes_checksum;
  50.  
  51. int             g_numtexinfo;
  52. texinfo_t       g_texinfo[MAX_MAP_TEXINFO];
  53. int             g_texinfo_checksum;
  54.  
  55. int             g_numfaces;
  56. dface_t         g_dfaces[MAX_MAP_FACES];
  57. int             g_dfaces_checksum;
  58.  
  59. int             g_numclipnodes;
  60. dclipnode_t     g_dclipnodes[MAX_MAP_CLIPNODES];
  61. int             g_dclipnodes_checksum;
  62.  
  63. int             g_numedges;
  64. dedge_t         g_dedges[MAX_MAP_EDGES];
  65. int             g_dedges_checksum;
  66.  
  67. int             g_nummarksurfaces;
  68. unsigned short  g_dmarksurfaces[MAX_MAP_MARKSURFACES];
  69. int             g_dmarksurfaces_checksum;
  70.  
  71. int             g_numsurfedges;
  72. int             g_dsurfedges[MAX_MAP_SURFEDGES];
  73. int             g_dsurfedges_checksum;
  74.  
  75. int             g_numentities;
  76. entity_t        g_entities[MAX_MAP_ENTITIES];
  77.  
  78. /*
  79.  * ===============
  80.  * FastChecksum
  81.  * ===============
  82.  */
  83.  
  84. static int      FastChecksum(const void* const buffer, int bytes)
  85. {
  86.     int             checksum = 0;
  87.     char*           buf = (char*)buffer;
  88.  
  89.     while (bytes--)
  90.     {
  91.         checksum = rotl(checksum, 4) ^ (*buf);
  92.         buf++;
  93.     }
  94.  
  95.     return checksum;
  96. }
  97.  
  98. /*
  99.  * ===============
  100.  * CompressVis
  101.  * ===============
  102.  */
  103. int             CompressVis(const byte* const src, const unsigned int src_length, byte* dest, unsigned int dest_length)
  104. {
  105.     unsigned int    j;
  106.     byte*           dest_p = dest;
  107.     unsigned int    current_length = 0;
  108.  
  109.     for (j = 0; j < src_length; j++)
  110.     {
  111.         current_length++;
  112.         hlassume(current_length <= dest_length, assume_COMPRESSVIS_OVERFLOW);
  113.  
  114.         *dest_p = src[j];
  115.         dest_p++;
  116.  
  117.         if (src[j])
  118.         {
  119.             continue;
  120.         }
  121.  
  122.         unsigned char   rep = 1;
  123.  
  124.         for (j++; j < src_length; j++)
  125.         {
  126.             if (src[j] || rep == 255)
  127.             {
  128.                 break;
  129.             }
  130.             else
  131.             {
  132.                 rep++;
  133.             }
  134.         }
  135.         current_length++;
  136.         hlassume(current_length <= dest_length, assume_COMPRESSVIS_OVERFLOW);
  137.  
  138.         *dest_p = rep;
  139.         dest_p++;
  140.         j--;
  141.     }
  142.  
  143.     return dest_p - dest;
  144. }
  145.  
  146. // =====================================================================================
  147. //  DecompressVis
  148. //      
  149. // =====================================================================================
  150. void            DecompressVis(const byte* src, byte* const dest, const unsigned int dest_length)
  151. {
  152.     unsigned int    current_length = 0;
  153.     int             c;
  154.     byte*           out;
  155.     int             row;
  156.  
  157.     row = (g_numleafs + 7) >> 3;
  158.     out = dest;
  159.  
  160.     do
  161.     {
  162.         if (*src)
  163.         {
  164.             current_length++;
  165.             hlassume(current_length <= dest_length, assume_DECOMPRESSVIS_OVERFLOW);
  166.  
  167.             *out = *src;
  168.             out++;
  169.             src++;
  170.             continue;
  171.         }
  172.  
  173.         c = src[1];
  174.         src += 2;
  175.         while (c)
  176.         {
  177.             current_length++;
  178.             hlassume(current_length <= dest_length, assume_DECOMPRESSVIS_OVERFLOW);
  179.  
  180.             *out = 0;
  181.             out++;
  182.             c--;
  183.  
  184.             if (out - dest >= row)
  185.             {
  186.                 return;
  187.             }
  188.         }
  189.     }
  190.     while (out - dest < row);
  191. }
  192.  
  193. //
  194. // =====================================================================================
  195. //
  196.  
  197. // =====================================================================================
  198. //  SwapBSPFile
  199. //      byte swaps all data in a bsp file
  200. // =====================================================================================
  201. static void     SwapBSPFile(const bool todisk)
  202. {
  203.     int             i, j, c;
  204.     dmodel_t*       d;
  205.     dmiptexlump_t*  mtl;
  206.  
  207.     // models       
  208.     for (i = 0; i < g_nummodels; i++)
  209.     {
  210.         d = &g_dmodels[i];
  211.  
  212.         for (j = 0; j < MAX_MAP_HULLS; j++)
  213.         {
  214.             d->headnode[j] = LittleLong(d->headnode[j]);
  215.         }
  216.  
  217.         d->visleafs = LittleLong(d->visleafs);
  218.         d->firstface = LittleLong(d->firstface);
  219.         d->numfaces = LittleLong(d->numfaces);
  220.  
  221.         for (j = 0; j < 3; j++)
  222.         {
  223.             d->mins[j] = LittleFloat(d->mins[j]);
  224.             d->maxs[j] = LittleFloat(d->maxs[j]);
  225.             d->origin[j] = LittleFloat(d->origin[j]);
  226.         }
  227.     }
  228.  
  229.     //
  230.     // vertexes
  231.     //
  232.     for (i = 0; i < g_numvertexes; i++)
  233.     {
  234.         for (j = 0; j < 3; j++)
  235.         {
  236.             g_dvertexes[i].point[j] = LittleFloat(g_dvertexes[i].point[j]);
  237.         }
  238.     }
  239.  
  240.     //
  241.     // planes
  242.     //      
  243.     for (i = 0; i < g_numplanes; i++)
  244.     {
  245.         for (j = 0; j < 3; j++)
  246.         {
  247.             g_dplanes[i].normal[j] = LittleFloat(g_dplanes[i].normal[j]);
  248.         }
  249.         g_dplanes[i].dist = LittleFloat(g_dplanes[i].dist);
  250.         g_dplanes[i].type = (planetypes)LittleLong(g_dplanes[i].type);
  251.     }
  252.  
  253.     //
  254.     // texinfos
  255.     //      
  256.     for (i = 0; i < g_numtexinfo; i++)
  257.     {
  258.         for (j = 0; j < 8; j++)
  259.         {
  260.             g_texinfo[i].vecs[0][j] = LittleFloat(g_texinfo[i].vecs[0][j]);
  261.         }
  262.         g_texinfo[i].miptex = LittleLong(g_texinfo[i].miptex);
  263.         g_texinfo[i].flags = LittleLong(g_texinfo[i].flags);
  264.     }
  265.  
  266.     //
  267.     // faces
  268.     //
  269.     for (i = 0; i < g_numfaces; i++)
  270.     {
  271.         g_dfaces[i].texinfo = LittleShort(g_dfaces[i].texinfo);
  272.         g_dfaces[i].planenum = LittleShort(g_dfaces[i].planenum);
  273.         g_dfaces[i].side = LittleShort(g_dfaces[i].side);
  274.         g_dfaces[i].lightofs = LittleLong(g_dfaces[i].lightofs);
  275.         g_dfaces[i].firstedge = LittleLong(g_dfaces[i].firstedge);
  276.         g_dfaces[i].numedges = LittleShort(g_dfaces[i].numedges);
  277.     }
  278.  
  279.     //
  280.     // nodes
  281.     //
  282.     for (i = 0; i < g_numnodes; i++)
  283.     {
  284.         g_dnodes[i].planenum = LittleLong(g_dnodes[i].planenum);
  285.         for (j = 0; j < 3; j++)
  286.         {
  287.             g_dnodes[i].mins[j] = LittleShort(g_dnodes[i].mins[j]);
  288.             g_dnodes[i].maxs[j] = LittleShort(g_dnodes[i].maxs[j]);
  289.         }
  290.         g_dnodes[i].children[0] = LittleShort(g_dnodes[i].children[0]);
  291.         g_dnodes[i].children[1] = LittleShort(g_dnodes[i].children[1]);
  292.         g_dnodes[i].firstface = LittleShort(g_dnodes[i].firstface);
  293.         g_dnodes[i].numfaces = LittleShort(g_dnodes[i].numfaces);
  294.     }
  295.  
  296.     //
  297.     // leafs
  298.     //
  299.     for (i = 0; i < g_numleafs; i++)
  300.     {
  301.         g_dleafs[i].contents = LittleLong(g_dleafs[i].contents);
  302.         for (j = 0; j < 3; j++)
  303.         {
  304.             g_dleafs[i].mins[j] = LittleShort(g_dleafs[i].mins[j]);
  305.             g_dleafs[i].maxs[j] = LittleShort(g_dleafs[i].maxs[j]);
  306.         }
  307.  
  308.         g_dleafs[i].firstmarksurface = LittleShort(g_dleafs[i].firstmarksurface);
  309.         g_dleafs[i].nummarksurfaces = LittleShort(g_dleafs[i].nummarksurfaces);
  310.         g_dleafs[i].visofs = LittleLong(g_dleafs[i].visofs);
  311.     }
  312.  
  313.     //
  314.     // clipnodes
  315.     //
  316.     for (i = 0; i < g_numclipnodes; i++)
  317.     {
  318.         g_dclipnodes[i].planenum = LittleLong(g_dclipnodes[i].planenum);
  319.         g_dclipnodes[i].children[0] = LittleShort(g_dclipnodes[i].children[0]);
  320.         g_dclipnodes[i].children[1] = LittleShort(g_dclipnodes[i].children[1]);
  321.     }
  322.  
  323.     //
  324.     // miptex
  325.     //
  326.     if (g_texdatasize)
  327.     {
  328.         mtl = (dmiptexlump_t*)g_dtexdata;
  329.         if (todisk)
  330.         {
  331.             c = mtl->nummiptex;
  332.         }
  333.         else
  334.         {
  335.             c = LittleLong(mtl->nummiptex);
  336.         }
  337.         mtl->nummiptex = LittleLong(mtl->nummiptex);
  338.         for (i = 0; i < c; i++)
  339.         {
  340.             mtl->dataofs[i] = LittleLong(mtl->dataofs[i]);
  341.         }
  342.     }
  343.  
  344.     //
  345.     // marksurfaces
  346.     //
  347.     for (i = 0; i < g_nummarksurfaces; i++)
  348.     {
  349.         g_dmarksurfaces[i] = LittleShort(g_dmarksurfaces[i]);
  350.     }
  351.  
  352.     //
  353.     // surfedges
  354.     //
  355.     for (i = 0; i < g_numsurfedges; i++)
  356.     {
  357.         g_dsurfedges[i] = LittleLong(g_dsurfedges[i]);
  358.     }
  359.  
  360.     //
  361.     // edges
  362.     //
  363.     for (i = 0; i < g_numedges; i++)
  364.     {
  365.         g_dedges[i].v[0] = LittleShort(g_dedges[i].v[0]);
  366.         g_dedges[i].v[1] = LittleShort(g_dedges[i].v[1]);
  367.     }
  368. }
  369.  
  370. // =====================================================================================
  371. //  CopyLump
  372. //      balh
  373. // =====================================================================================
  374. static int      CopyLump(int lump, void* dest, int size, const dheader_t* const header)
  375. {
  376.     int             length, ofs;
  377.  
  378.     length = header->lumps[lump].filelen;
  379.     ofs = header->lumps[lump].fileofs;
  380.  
  381.     if (length % size)
  382.     {
  383.         Error("LoadBSPFile: odd lump size");
  384.     }
  385.  
  386.     memcpy(dest, (byte*) header + ofs, length);
  387.  
  388.     return length / size;
  389. }
  390.  
  391.  
  392. // =====================================================================================
  393. //  LoadBSPFile
  394. //      balh
  395. // =====================================================================================
  396. void            LoadBSPFile(const char* const filename)
  397. {
  398.     dheader_t* header;
  399.     LoadFile(filename, (char**)&header);
  400.     LoadBSPImage(header);
  401. }
  402.  
  403. // =====================================================================================
  404. //  LoadBSPImage
  405. //      balh
  406. // =====================================================================================
  407. void            LoadBSPImage(dheader_t* const header)
  408. {
  409.     unsigned int     i;
  410.  
  411.     // swap the header
  412.     for (i = 0; i < sizeof(dheader_t) / 4; i++)
  413.     {
  414.         ((int*)header)[i] = LittleLong(((int*)header)[i]);
  415.     }
  416.  
  417.     if (header->version != BSPVERSION)
  418.     {
  419.         Error("BSP is version %i, not %i", header->version, BSPVERSION);
  420.     }
  421.  
  422.     g_nummodels = CopyLump(LUMP_MODELS, g_dmodels, sizeof(dmodel_t), header);
  423.     g_numvertexes = CopyLump(LUMP_VERTEXES, g_dvertexes, sizeof(dvertex_t), header);
  424.     g_numplanes = CopyLump(LUMP_PLANES, g_dplanes, sizeof(dplane_t), header);
  425.     g_numleafs = CopyLump(LUMP_LEAFS, g_dleafs, sizeof(dleaf_t), header);
  426.     g_numnodes = CopyLump(LUMP_NODES, g_dnodes, sizeof(dnode_t), header);
  427.     g_numtexinfo = CopyLump(LUMP_TEXINFO, g_texinfo, sizeof(texinfo_t), header);
  428.     g_numclipnodes = CopyLump(LUMP_CLIPNODES, g_dclipnodes, sizeof(dclipnode_t), header);
  429.     g_numfaces = CopyLump(LUMP_FACES, g_dfaces, sizeof(dface_t), header);
  430.     g_nummarksurfaces = CopyLump(LUMP_MARKSURFACES, g_dmarksurfaces, sizeof(g_dmarksurfaces[0]), header);
  431.     g_numsurfedges = CopyLump(LUMP_SURFEDGES, g_dsurfedges, sizeof(g_dsurfedges[0]), header);
  432.     g_numedges = CopyLump(LUMP_EDGES, g_dedges, sizeof(dedge_t), header);
  433.     g_texdatasize = CopyLump(LUMP_TEXTURES, g_dtexdata, 1, header);
  434.     g_visdatasize = CopyLump(LUMP_VISIBILITY, g_dvisdata, 1, header);
  435.     g_lightdatasize = CopyLump(LUMP_LIGHTING, g_dlightdata, 1, header);
  436.     g_entdatasize = CopyLump(LUMP_ENTITIES, g_dentdata, 1, header);
  437.  
  438.     Free(header);                                          // everything has been copied out
  439.  
  440.     //
  441.     // swap everything
  442.     //      
  443.     SwapBSPFile(false);
  444.  
  445.     g_dmodels_checksum = FastChecksum(g_dmodels, g_nummodels * sizeof(g_dmodels[0]));
  446.     g_dvertexes_checksum = FastChecksum(g_dvertexes, g_numvertexes * sizeof(g_dvertexes[0]));
  447.     g_dplanes_checksum = FastChecksum(g_dplanes, g_numplanes * sizeof(g_dplanes[0]));
  448.     g_dleafs_checksum = FastChecksum(g_dleafs, g_numleafs * sizeof(g_dleafs[0]));
  449.     g_dnodes_checksum = FastChecksum(g_dnodes, g_numnodes * sizeof(g_dnodes[0]));
  450.     g_texinfo_checksum = FastChecksum(g_texinfo, g_numtexinfo * sizeof(g_texinfo[0]));
  451.     g_dclipnodes_checksum = FastChecksum(g_dclipnodes, g_numclipnodes * sizeof(g_dclipnodes[0]));
  452.     g_dfaces_checksum = FastChecksum(g_dfaces, g_numfaces * sizeof(g_dfaces[0]));
  453.     g_dmarksurfaces_checksum = FastChecksum(g_dmarksurfaces, g_nummarksurfaces * sizeof(g_dmarksurfaces[0]));
  454.     g_dsurfedges_checksum = FastChecksum(g_dsurfedges, g_numsurfedges * sizeof(g_dsurfedges[0]));
  455.     g_dedges_checksum = FastChecksum(g_dedges, g_numedges * sizeof(g_dedges[0]));
  456.     g_dtexdata_checksum = FastChecksum(g_dtexdata, g_numedges * sizeof(g_dtexdata[0]));
  457.     g_dvisdata_checksum = FastChecksum(g_dvisdata, g_visdatasize * sizeof(g_dvisdata[0]));
  458.     g_dlightdata_checksum = FastChecksum(g_dlightdata, g_lightdatasize * sizeof(g_dlightdata[0]));
  459.     g_dentdata_checksum = FastChecksum(g_dentdata, g_entdatasize * sizeof(g_dentdata[0]));
  460. }
  461.  
  462. //
  463. // =====================================================================================
  464. //
  465.  
  466. // =====================================================================================
  467. //  AddLump
  468. //      balh
  469. // =====================================================================================
  470. static void     AddLump(int lumpnum, void* data, int len, dheader_t* header, FILE* bspfile)
  471. {
  472.     lump_t* lump =&header->lumps[lumpnum];
  473.     lump->fileofs = LittleLong(ftell(bspfile));
  474.     lump->filelen = LittleLong(len);
  475.     SafeWrite(bspfile, data, (len + 3) & ~3);
  476. }
  477.  
  478. // =====================================================================================
  479. //  WriteBSPFile
  480. //      Swaps the bsp file in place, so it should not be referenced again
  481. // =====================================================================================
  482. void            WriteBSPFile(const char* const filename)
  483. {
  484.     dheader_t       outheader;
  485.     dheader_t*      header;
  486.     FILE*           bspfile;
  487.  
  488.     header = &outheader;
  489.     memset(header, 0, sizeof(dheader_t));
  490.  
  491.     SwapBSPFile(true);
  492.  
  493.     header->version = LittleLong(BSPVERSION);
  494.  
  495.     bspfile = SafeOpenWrite(filename);
  496.     SafeWrite(bspfile, header, sizeof(dheader_t));         // overwritten later
  497.  
  498.     //      LUMP TYPE       DATA            LENGTH                              HEADER  BSPFILE   
  499.     AddLump(LUMP_PLANES,    g_dplanes,      g_numplanes * sizeof(dplane_t),     header, bspfile);
  500.     AddLump(LUMP_LEAFS,     g_dleafs,       g_numleafs * sizeof(dleaf_t),       header, bspfile);
  501.     AddLump(LUMP_VERTEXES,  g_dvertexes,    g_numvertexes * sizeof(dvertex_t),  header, bspfile);
  502.     AddLump(LUMP_NODES,     g_dnodes,       g_numnodes * sizeof(dnode_t),       header, bspfile);
  503.     AddLump(LUMP_TEXINFO,   g_texinfo,      g_numtexinfo * sizeof(texinfo_t),   header, bspfile);
  504.     AddLump(LUMP_FACES,     g_dfaces,       g_numfaces * sizeof(dface_t),       header, bspfile);
  505.     AddLump(LUMP_CLIPNODES, g_dclipnodes,   g_numclipnodes * sizeof(dclipnode_t), header, bspfile);
  506.  
  507.     AddLump(LUMP_MARKSURFACES, g_dmarksurfaces, g_nummarksurfaces * sizeof(g_dmarksurfaces[0]), header, bspfile);
  508.     AddLump(LUMP_SURFEDGES, g_dsurfedges,   g_numsurfedges * sizeof(g_dsurfedges[0]), header, bspfile);
  509.     AddLump(LUMP_EDGES,     g_dedges,       g_numedges * sizeof(dedge_t),       header, bspfile);
  510.     AddLump(LUMP_MODELS,    g_dmodels,      g_nummodels * sizeof(dmodel_t),     header, bspfile);
  511.  
  512.     AddLump(LUMP_LIGHTING,  g_dlightdata,   g_lightdatasize,                    header, bspfile);
  513.     AddLump(LUMP_VISIBILITY,g_dvisdata,     g_visdatasize,                      header, bspfile);
  514.     AddLump(LUMP_ENTITIES,  g_dentdata,     g_entdatasize,                      header, bspfile);
  515.     AddLump(LUMP_TEXTURES,  g_dtexdata,     g_texdatasize,                      header, bspfile);
  516.  
  517.     fseek(bspfile, 0, SEEK_SET);
  518.     SafeWrite(bspfile, header, sizeof(dheader_t));
  519.  
  520.     fclose(bspfile);
  521. }
  522.  
  523. //
  524. // =====================================================================================
  525. //
  526.  
  527. #define ENTRIES(a)        (sizeof(a)/sizeof(*(a)))
  528. #define ENTRYSIZE(a)    (sizeof(*(a)))
  529.  
  530. // =====================================================================================
  531. //  ArrayUsage
  532. //      blah
  533. // =====================================================================================
  534. static int      ArrayUsage(const char* const szItem, const int items, const int maxitems, const int itemsize)
  535. {
  536.     float           percentage = maxitems ? items * 100.0 / maxitems : 0.0;
  537.  
  538.     Log("%-12s  %7i/%-7i  %7i/%-7i  (%4.1f%%)\n", szItem, items, maxitems, items * itemsize, maxitems * itemsize, percentage);
  539.  
  540.     return items * itemsize;
  541. }
  542.  
  543. // =====================================================================================
  544. //  GlobUsage
  545. //      pritn out global ussage line in chart
  546. // =====================================================================================
  547. static int      GlobUsage(const char* const szItem, const int itemstorage, const int maxstorage)
  548. {
  549.     float           percentage = maxstorage ? itemstorage * 100.0 / maxstorage : 0.0;
  550.  
  551.     Log("%-12s     [variable]    %7i/%-7i  (%4.1f%%)\n", szItem, itemstorage, maxstorage, percentage);
  552.  
  553.     return itemstorage;
  554. }
  555.  
  556. // =====================================================================================
  557. //  PrintBSPFileSizes
  558. //      Dumps info about current file
  559. // =====================================================================================
  560. void            PrintBSPFileSizes()
  561. {
  562.     int             numtextures = g_texdatasize ? ((dmiptexlump_t*)g_dtexdata)->nummiptex : 0;
  563.     int             totalmemory = 0;
  564.  
  565.     Log("\n");
  566.     Log("Object names  Objects/Maxobjs  Memory / Maxmem  Fullness\n");
  567.     Log("------------  ---------------  ---------------  --------\n");
  568.  
  569.     totalmemory += ArrayUsage("models", g_nummodels, ENTRIES(g_dmodels), ENTRYSIZE(g_dmodels));
  570.     totalmemory += ArrayUsage("planes", g_numplanes, ENTRIES(g_dplanes), ENTRYSIZE(g_dplanes));
  571.     totalmemory += ArrayUsage("vertexes", g_numvertexes, ENTRIES(g_dvertexes), ENTRYSIZE(g_dvertexes));
  572.     totalmemory += ArrayUsage("nodes", g_numnodes, ENTRIES(g_dnodes), ENTRYSIZE(g_dnodes));
  573.     totalmemory += ArrayUsage("texinfos", g_numtexinfo, ENTRIES(g_texinfo), ENTRYSIZE(g_texinfo));
  574.     totalmemory += ArrayUsage("faces", g_numfaces, ENTRIES(g_dfaces), ENTRYSIZE(g_dfaces));
  575.     totalmemory += ArrayUsage("clipnodes", g_numclipnodes, ENTRIES(g_dclipnodes), ENTRYSIZE(g_dclipnodes));
  576.     totalmemory += ArrayUsage("leaves", g_numleafs, ENTRIES(g_dleafs), ENTRYSIZE(g_dleafs));
  577.     totalmemory += ArrayUsage("marksurfaces", g_nummarksurfaces, ENTRIES(g_dmarksurfaces), ENTRYSIZE(g_dmarksurfaces));
  578.     totalmemory += ArrayUsage("surfedges", g_numsurfedges, ENTRIES(g_dsurfedges), ENTRYSIZE(g_dsurfedges));
  579.     totalmemory += ArrayUsage("edges", g_numedges, ENTRIES(g_dedges), ENTRYSIZE(g_dedges));
  580.  
  581.     totalmemory += GlobUsage("texdata", g_texdatasize, g_max_map_miptex);
  582.     totalmemory += GlobUsage("lightdata", g_lightdatasize, sizeof(g_dlightdata));
  583.     totalmemory += GlobUsage("visdata", g_visdatasize, sizeof(g_dvisdata));
  584.     totalmemory += GlobUsage("entdata", g_entdatasize, sizeof(g_dentdata));
  585.  
  586.     Log("%i textures referenced\n", numtextures);
  587.  
  588.     Log("=== Total BSP file data space used: %d bytes ===\n", totalmemory);
  589. }
  590.  
  591.  
  592. // =====================================================================================
  593. //  ParseEpair
  594. //      entity key/value pairs
  595. // =====================================================================================
  596. epair_t*        ParseEpair()
  597. {
  598.     epair_t*        e;
  599.  
  600.     e = (epair_t*)Alloc(sizeof(epair_t));
  601.  
  602.     if (strlen(g_token) >= MAX_KEY - 1)
  603.         Error("ParseEpair: Key token too long (%i > MAX_KEY)", (int)strlen(g_token));
  604.  
  605.     e->key = strdup(g_token);
  606.     GetToken(false);
  607.  
  608.     if (strlen(g_token) >= MAX_VALUE - 1)
  609.         Error("ParseEpar: Value token too long (%i > MAX_VALUE)", (int)strlen(g_token));
  610.  
  611.     e->value = strdup(g_token);
  612.  
  613.     return e;
  614. }
  615.  
  616. /*
  617.  * ================
  618.  * ParseEntity
  619.  * ================
  620.  */
  621.  
  622. #ifdef ZHLT_INFO_COMPILE_PARAMETERS
  623. // AJM: each tool should have its own version of GetParamsFromEnt which parseentity calls
  624. extern void     GetParamsFromEnt(entity_t* mapent);
  625. #endif
  626.  
  627. bool            ParseEntity()
  628. {
  629.     epair_t*        e;
  630.     entity_t*       mapent;
  631.  
  632.     if (!GetToken(true))
  633.     {
  634.         return false;
  635.     }
  636.  
  637.     if (strcmp(g_token, "{"))
  638.     {
  639.         Error("ParseEntity: { not found");
  640.     }
  641.  
  642.     if (g_numentities == MAX_MAP_ENTITIES)
  643.     {
  644.         Error("g_numentities == MAX_MAP_ENTITIES");
  645.     }
  646.  
  647.     mapent = &g_entities[g_numentities];
  648.     g_numentities++;
  649.  
  650.     while (1)
  651.     {
  652.         if (!GetToken(true))
  653.         {
  654.             Error("ParseEntity: EOF without closing brace");
  655.         }
  656.         if (!strcmp(g_token, "}"))
  657.         {
  658.             break;
  659.         }
  660.         e = ParseEpair();
  661.         e->next = mapent->epairs;
  662.         mapent->epairs = e;
  663.     }
  664.  
  665. #ifdef ZHLT_INFO_COMPILE_PARAMETERS // AJM
  666.     if (!strcmp(ValueForKey(mapent, "classname"), "info_compile_parameters"))
  667.     {
  668.         Log("Map entity info_compile_parameters detected, using compile settings\n");
  669.         GetParamsFromEnt(mapent);
  670.     }
  671. #endif
  672.  
  673.     return true;
  674. }
  675.  
  676. // =====================================================================================
  677. //  ParseEntities
  678. //      Parses the dentdata string into entities
  679. // =====================================================================================
  680. void            ParseEntities()
  681. {
  682.     g_numentities = 0;
  683.     ParseFromMemory(g_dentdata, g_entdatasize);
  684.  
  685.     while (ParseEntity())
  686.     {
  687.     }
  688. }
  689.  
  690. // =====================================================================================
  691. //  UnparseEntities
  692. //      Generates the dentdata string from all the entities
  693. // =====================================================================================
  694. void            UnparseEntities()
  695. {
  696.     char*           buf;
  697.     char*           end;
  698.     epair_t*        ep;
  699.     char            line[MAXTOKEN];
  700.     int             i;
  701.  
  702.     buf = g_dentdata;
  703.     end = buf;
  704.     *end = 0;
  705.  
  706.     for (i = 0; i < g_numentities; i++)
  707.     {
  708.         ep = g_entities[i].epairs;
  709.         if (!ep)
  710.         {
  711.             continue;                                      // ent got removed
  712.         }
  713.  
  714.         strcat(end, "{\n");
  715.         end += 2;
  716.  
  717.         for (ep = g_entities[i].epairs; ep; ep = ep->next)
  718.         {
  719.             sprintf(line, "\"%s\" \"%s\"\n", ep->key, ep->value);
  720.             strcat(end, line);
  721.             end += strlen(line);
  722.         }
  723.         strcat(end, "}\n");
  724.         end += 2;
  725.  
  726.         if (end > buf + MAX_MAP_ENTSTRING)
  727.         {
  728.             Error("Entity text too long");
  729.         }
  730.     }
  731.     g_entdatasize = end - buf + 1;
  732. }
  733.  
  734. // =====================================================================================
  735. //  SetKeyValue
  736. //      makes a keyvalue
  737. // =====================================================================================
  738. void            SetKeyValue(entity_t* ent, const char* const key, const char* const value)
  739. {
  740.     epair_t*        ep;
  741.  
  742.     for (ep = ent->epairs; ep; ep = ep->next)
  743.     {
  744.         if (!strcmp(ep->key, key))
  745.         {
  746.             Free(ep->value);
  747.             ep->value = strdup(value);
  748.             return;
  749.         }
  750.     }
  751.     ep = (epair_t*)Alloc(sizeof(*ep));
  752.     ep->next = ent->epairs;
  753.     ent->epairs = ep;
  754.     ep->key = strdup(key);
  755.     ep->value = strdup(value);
  756. }
  757.  
  758. // =====================================================================================
  759. //  ValueForKey
  760. //      returns the value for a passed entity and key
  761. // =====================================================================================
  762. const char*     ValueForKey(const entity_t* const ent, const char* const key)
  763. {
  764.     epair_t*        ep;
  765.  
  766.     for (ep = ent->epairs; ep; ep = ep->next)
  767.     {
  768.         if (!strcmp(ep->key, key))
  769.         {
  770.             return ep->value;
  771.         }
  772.     }
  773.     return "";
  774. }
  775.  
  776. // =====================================================================================
  777. //  IntForKey
  778. // =====================================================================================
  779. int             IntForKey(const entity_t* const ent, const char* const key)
  780. {
  781.     return atoi(ValueForKey(ent, key));
  782. }
  783.  
  784. // =====================================================================================
  785. //  FloatForKey
  786. // =====================================================================================
  787. vec_t           FloatForKey(const entity_t* const ent, const char* const key)
  788. {
  789.     return atof(ValueForKey(ent, key));
  790. }
  791.  
  792. // =====================================================================================
  793. //  GetVectorForKey
  794. //      returns value for key in vec[0-2]
  795. // =====================================================================================
  796. void            GetVectorForKey(const entity_t* const ent, const char* const key, vec3_t vec)
  797. {
  798.     const char*     k;
  799.     double          v1, v2, v3;
  800.  
  801.     k = ValueForKey(ent, key);
  802.     // scanf into doubles, then assign, so it is vec_t size independent
  803.     v1 = v2 = v3 = 0;
  804.     sscanf(k, "%lf %lf %lf", &v1, &v2, &v3);
  805.     vec[0] = v1;
  806.     vec[1] = v2;
  807.     vec[2] = v3;
  808. }
  809.  
  810. // =====================================================================================
  811. //  FindTargetEntity
  812. //      
  813. // =====================================================================================
  814. entity_t *FindTargetEntity(const char* const target)
  815. {
  816.     int             i;
  817.     const char*     n;
  818.  
  819.     for (i = 0; i < g_numentities; i++)
  820.     {
  821.         n = ValueForKey(&g_entities[i], "targetname");
  822.         if (!strcmp(n, target))
  823.         {
  824.             return &g_entities[i];
  825.         }
  826.     }
  827.  
  828.     return NULL;
  829. }
  830.  
  831.  
  832. void            dtexdata_init()
  833. {
  834.     g_dtexdata = (byte*)AllocBlock(g_max_map_miptex);
  835.     hlassume(g_dtexdata != NULL, assume_NoMemory);
  836. }
  837.  
  838. void CDECL      dtexdata_free()
  839. {
  840.     FreeBlock(g_dtexdata);
  841.     g_dtexdata = NULL;
  842. }
  843.  
  844. // =====================================================================================
  845. //  GetTextureByNumber
  846. //      Touchy function, can fail with a page fault if all the data isnt kosher 
  847. //      (i.e. map was compiled with missing textures)
  848. // =====================================================================================
  849. char*           GetTextureByNumber(int texturenumber)
  850. {
  851.     texinfo_t*      info;
  852.     miptex_t*       miptex;
  853.     int             ofs;
  854.  
  855.     info = &g_texinfo[texturenumber];
  856.     ofs = ((dmiptexlump_t*)g_dtexdata)->dataofs[info->miptex];
  857.     miptex = (miptex_t*)(&g_dtexdata[ofs]);
  858.  
  859.     return miptex->name;
  860. }
  861.  
  862. // =====================================================================================
  863. //  EntityForModel
  864. //      returns entity addy for given modelnum
  865. // =====================================================================================
  866. entity_t*       EntityForModel(const int modnum)
  867. {
  868.     int             i;
  869.     const char*     s;
  870.     char            name[16];
  871.  
  872.     sprintf(name, "*%i", modnum);
  873.     // search the entities for one using modnum
  874.     for (i = 0; i < g_numentities; i++)
  875.     {
  876.         s = ValueForKey(&g_entities[i], "model");
  877.         if (!strcmp(s, name))
  878.         {
  879.             return &g_entities[i];
  880.         }
  881.     }
  882.  
  883.     return &g_entities[0];
  884. }